
#include "Header.h"
#include "SoundMath.h"

//#include <intrin.h>

extern "C"
{
	DECLSPEC void STDCALL Common_Modulizer_Oscilator_Process(
		int length, int waveformBufferLength, double* n_currentSample
		, double* pitch, double* frequency, double* volyme, double* tune
		, double* waveformBuffer, double* outputBuffer, double* runAndIdleAmp, double* mCurrentSampleRestartAt
		, double sampleRate)
	{
		double waveFormBufferLength_in1 = 1.0 / waveformBufferLength;
		double currentSample = *n_currentSample;
		bool isPitch = pitch != 0;

		// Why F#????
		double sampleRate_m_92 = sampleRate * 92.50;
		// Why 22?
		double sampleRate_m_22 = sampleRate * 22;

		for (int s = 0; s < length; s++)
		{
			if (mCurrentSampleRestartAt[s] != 0.0)
			{
				currentSample = 0;
				mCurrentSampleRestartAt[s] = 0.0;
			}

			double freq;
			if (isPitch)
			{
				// Rference: http://www.intmath.com/trigonometric-graphs/music.php
				// Why F#????
				freq = SoundMath::Pow_Note(pitch[s] + tune[s]) * sampleRate_m_92;
			}
			else
			{
				if (tune[s] != 0.0)
				{
					// Why 22?
					double tone = SoundMath::PowNote * SoundMath::Pow_Note(tune[s]) * sampleRate - SoundMath::PowNote;
					freq = 22 * frequency[s] + tone;
				}
				else
				{
					// Why 22?
					freq = frequency[s] * sampleRate_m_22;
				}
			}
			
			if (freq > 10000000.0 || freq < -10000000.0)
			{
				freq = 0;
			}

			// Reference: http://www.cplusplus.com/forum/beginner/103457/
			currentSample += freq * waveFormBufferLength_in1;
			if (currentSample >= waveformBufferLength)
			{
				//currentSample %= waveFormBufferLength;
				currentSample -= waveformBufferLength;
				if (currentSample >= waveformBufferLength)
				{
					//currentSample = fmod(currentSample, waveFormBufferLength);
					currentSample = (int)currentSample % waveformBufferLength + (currentSample - (int)currentSample);
				}
			}
			else if (currentSample < 0)
			{
				currentSample = 0;
			}

			if (runAndIdleAmp[s] != 0.0)
			{
				outputBuffer[s] = waveformBuffer[(int)currentSample] * volyme[s];
			}
			else
			{
				outputBuffer[s] = 0;
			}
		}

		*n_currentSample = currentSample;
	}
}